﻿using Serilog;
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;

namespace WatchDog;

public class ProcessHelper
{
    /// <summary>
    /// 判断指定的程序是否正在运行
    /// </summary>
    /// <param name="fullPath"></param>
    /// <returns></returns>
    public static bool IsRuning(string fullPath)
    {
        try
        {
            var process = Process.GetProcessesByName(Path.GetFileNameWithoutExtension(fullPath));
            return process.Any(c => c.MainModule.FileName == fullPath);
        }
        catch
        {
            return false;
        }
    }

    /// <summary>
    /// 获取程序运行时长（分钟）
    /// </summary>
    /// <param name="fullPath"></param>
    /// <returns></returns>
    public static double GetRunningTotalMinutes(string fullPath)
    {
        try
        {
            var process = Process.GetProcessesByName(Path.GetFileNameWithoutExtension(fullPath));
            var m = process.FirstOrDefault(c => c.MainModule.FileName == fullPath);
            if (m != default)
            {
                return (DateTime.Now - m.StartTime).TotalMinutes;
            }
            return 0;
        }
        catch
        {
            return 0;
        }
    }

    /// <summary>
    /// 启动指定的程序
    /// </summary>
    /// <param name="fullPath"></param>
    public static void Start(string fullPath)
    {
        //获得当前登录的Windows用户标示
        System.Security.Principal.WindowsIdentity identity = System.Security.Principal.WindowsIdentity.GetCurrent();
        System.Security.Principal.WindowsPrincipal principal = new System.Security.Principal.WindowsPrincipal(identity);
        //判断当前登录用户是否为管理员
        if (principal.IsInRole(System.Security.Principal.WindowsBuiltInRole.Administrator))
        {
            try
            {
                // 当前进程是否在用户交互模式中运行
                if (Environment.UserInteractive)
                {
                    var proc = new Process();
                    proc.StartInfo.FileName = fullPath;
                    proc.StartInfo.WorkingDirectory = Path.GetDirectoryName(fullPath);
                    proc.StartInfo.CreateNoWindow = true;
                    proc.Start();
                }
                else
                {
                    Log.Logger.Debug($"启动 {fullPath}");
                    Windows服务启动GUI进程.Start(fullPath, Path.GetDirectoryName(fullPath), true);
                }
            }
            catch (Exception ex)
            {
                Log.Logger.Error(ex, $"启动{fullPath}时出错");
            }
        }
        else
        {
            try
            {
                // 当前进程是否在用户交互模式中运行
                if (Environment.UserInteractive)
                {
                    //创建启动对象
                    System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
                    startInfo.UseShellExecute = true;
                    startInfo.WorkingDirectory = Path.GetDirectoryName(fullPath);
                    startInfo.FileName = Path.GetFileName(fullPath);
                    //设置启动动作,确保以管理员身份运行
                    startInfo.Verb = "runas";

                    //重新已管理员身份启动;
                    System.Diagnostics.Process.Start(startInfo);
                }
                else
                {
                    Log.Logger.Debug($"启动 {fullPath}");

                    Windows服务启动GUI进程.Start(fullPath, Path.GetDirectoryName(fullPath), true);
                }
            }
            catch (Exception ex)
            {
                Log.Logger.Error(ex, $"启动{fullPath}时出错");
            }
        }

    }

    /// <summary>
    /// 停止指定的程序
    /// </summary>
    /// <param name="fullPath"></param>
    public static void Stop(string fullPath)
    {
        try
        {
            var process = Process.GetProcessesByName(Path.GetFileNameWithoutExtension(fullPath))
                .Where(c => c.MainModule.FileName == fullPath);

            if (process.Any())
            {
                foreach (var item in process)
                {
                    item.Kill();
                }
            }
        }
        catch (Exception ex)
        {
            Log.Logger.Error(ex, $"结束{fullPath}时出错");
        }
    }
}
